local Msg = require("core.Msg")
local Lang = require("common.Lang")
local ObjHuman = require("core.ObjHuman")
local Broadcast = require("broadcast.Broadcast")
local sbConfig = require("excel.Shenbing")
local sbMainConfig = sbConfig.shenbing
local feedConfig = sbConfig.feed
local ItemDefine = require("bag.ItemDefine")
local SkillNotify  = require("skill.Notify")
local BagLogic = require("bag.BagLogic")
local SkillExcel = require("excel.Skill").Skill
local Grid = require("bag.Grid")
local Status = require("scene.Status")
local RankDefine = require("rank.RankDefine")
local RoleAttr = require("role.RoleAttr")
local TaskCallbacks = require("task.TaskCallbacks")
local TaskDefine = require("task.Define")
local Cmds = require("buffer.Cmds")
local AcvityDefine = require("activity.Define")
local Log = require("common.Log")
local Buffer = require("buffer.Buffer")
local CoolDown = require("skill.CoolDown")
local HtmlUtil = require("common.HtmlUtil")
local YYDaBiao = require("activity.operate.DaBiao")
local OfficialLogic = require("official.OfficialLogic")

local MAX_STRENGTH_LV  =  99

local ZHANDOULI_CALC = {15, 20, 25, 30}
function init()
    for k, v in pairs(sbMainConfig) do
        for i = 1, #v.haveSkill do
            if SkillExcel[v.haveSkill[i]] then
                SkillExcel[v.haveSkill[i]].sb = SkillExcel[v.haveSkill[i]].sb or k
            end
        end
        v.starTotalAttr = {[0]={}}
        v.starTotalEquipAttr = {[0]={}}
        if v.starEquipAttr[0] then
            for j = 1, #v.starEquipAttr[0] do
                v.starTotalEquipAttr[0][v.starEquipAttr[0][j][1] ] = v.starEquipAttr[0][j][2]
            end
        end
        for i = 1, 5 do
            v.starTotalAttr[i] = {}
            for j = 1, #v.starAttr[i] do
                v.starTotalAttr[i][ v.starAttr[i][j][1] ] = v.starAttr[i][j][2]
            end
            for kk, vv in pairs(v.starTotalAttr[i-1]) do
                v.starTotalAttr[i][kk] = v.starTotalAttr[i][kk] or 0
                v.starTotalAttr[i][kk] = v.starTotalAttr[i][kk] + vv
            end
            --佩带属性
            v.starTotalEquipAttr[i] = {}
            if v.starEquipAttr[i] then
                for j = 1, #v.starEquipAttr[i] do
                    v.starTotalEquipAttr[i][v.starEquipAttr[i][j][1] ] = v.starEquipAttr[i][j][2]
                end
            end
            for kk, vv in pairs(v.starTotalEquipAttr[i-1]) do
                v.starTotalEquipAttr[i][kk] = v.starTotalEquipAttr[i][kk] or 0
                v.starTotalEquipAttr[i][kk] = v.starTotalEquipAttr[i][kk] + vv
            end

        end
        local strengConf = sbConfig[v.sbName]
        strengConf[0].attr = {}

        for i = 1, #v.initAttr do
            strengConf[0].attr[v.initAttr[i][1]] = v.initAttr[i][2]
        end
        for i = 1, MAX_STRENGTH_LV do
            strengConf[i].attr = strengConf[i].attr or {}
            for t, val in pairs(strengConf[i-1].attr) do
                strengConf[i].attr[t] = val
            end
            for j = 1, #strengConf[i-1].addAttrCount do
                local t = strengConf[i-1].addAttrCount[j]
                strengConf[i].attr[t.type] = strengConf[i].attr[t.type]  or 0
                strengConf[i].attr[t.type] = strengConf[i].attr[t.type] + t.value
            end
        end
    end
end

init()




CacheGrid = CacheGrid or {}
--type 1激活，2升星, 3激活绝技
local function makeMaterialGrid(human, msg, id, itemID, cnt, type)
    if CacheGrid[id] == nil then
        CacheGrid[id]= {}
    end
    if CacheGrid[id][type] == nil then
        CacheGrid[id][type] = {}
        Grid.create(CacheGrid[id][type], itemID, cnt)
    end
    CacheGrid[id][type].cnt = cnt
    Grid.makeItem( CacheGrid[id][type], msg, 0, human)
end



function setShenbingInfo(human, id, info, isOther)
    local config = sbMainConfig[id]
    info.id = id
    info.type = config.type
    info.name = config.sbMingzi

    info.bodyId[1] = config.bodyId[1] or 0
    info.bodyId[2] = config.bodyId[2] or 0
    info.bodyId[0] = 2
    info.icon[1] = config.icon[1] or 0
    info.icon[2] = config.icon[2] or 0
    info.icon[0] = 2
    info.awake = config.awake
    info.awakeBodyID = config.awakeBodyID
    info.awakeWeaponID = config.awakeWeaponID
    info.awakeDesc = config.awakeDesc
    local curConf = sbConfig[config.sbName]
    local data = ObjHuman.getShenbing(human, id)
    if data then
        info.isHave = 1
        info.isPutOn = id == human.db.putonShenbing and 1 or 0
        info.isJinhua = data.jinhua
        info.lv = data.lv
        info.deng = data.deng
        info.star = data.star
        info.jujiDesc = "无敌"
        info.feed = isFeedFull(human, id, config, data) and 1 or 0
        info.juejiActive = data.jueji
    else
        info.isHave = 0
        info.isPutOn = 0
        info.isJinhua = 0
        info.lv = 0
        info.deng = 0
        info.star = config.initStar or 0
        info.jujiDesc = ""
        info.feed = 0
        info.juejiActive = 0
    end

    if info.star >= 5 then
        info.nextStarAttr[0] = 0
        info.nextStarEquipAttr[0] = 0
    else
        local attr = config.starAttr[info.star+1]
        for i = 1, #attr do
            info.nextStarAttr[i].key = attr[i][1]
            info.nextStarAttr[i].value = attr[i][2]
        end
        info.nextStarAttr[0] = #attr

        info.nextStarEquipAttr[0] = 0
        attr = config.starEquipAttr[info.star+1]
        if attr then
            for i = 1, #attr do
                info.nextStarEquipAttr[i].key = attr[i][1]
                info.nextStarEquipAttr[i].value = attr[i][2]
            end
            info.nextStarEquipAttr[0] = #attr
        end
    end
    --当前佩带属性
    info.equipAttr[0] = 0
    local attr = config.starTotalEquipAttr[info.star]
    if attr then
        for k, v in pairs(attr) do
            info.equipAttr[0] = info.equipAttr[0] + 1
            info.equipAttr[info.equipAttr[0]].key = k
            info.equipAttr[info.equipAttr[0]].value = v
        end
    end

    local lv = data and data.lv or 1
    info.skillMaxLv = curConf[lv].skillMaxLv
    attr = getAttr(id, info.lv, info.deng, info.star, nil, data)
    local len = 0
    for k, v in pairs(attr) do
        len = len + 1
        info.attr[len].key = k
        info.attr[len].value = v
    end
    info.attr[0] = len
    local skillZdl = getSkillZhandouli(human, id)
    info.zhandouli = RoleAttr.calHumanPower(attr) + skillZdl
    info.nextLvZhandouli  = 0
    if info.deng == 8 then
        if curConf[lv + 1] then
            attr = getAttr(id, info.lv + 1, 0, info.star)
            info.nextLvZhandouli = RoleAttr.calHumanPower(attr) + skillZdl
        end
    else
        attr = getAttr(id, info.lv,  info.deng+1, info.star)
        info.nextLvZhandouli = RoleAttr.calHumanPower(attr) + skillZdl
    end
    info.nextStarZhandouli = 0
    if info.star < 5 then
        attr = getAttr(id, info.lv,  info.deng, info.star+1)
        info.nextStarZhandouli = RoleAttr.calHumanPower(attr) + skillZdl
    end
    len = #config.haveSkill
    if len > 4 then
        len =4
    end
    for i = 1, len do
        SkillNotify.setSkillData(human, config.haveSkill[i], info.skill[i], data and data.skillLv[i-1] or 0, data and ObjHuman.getSkillLevelUp(human, config.haveSkill[i]), isOther)
    end
    info.skill[0] = len


    info.jinhuaLv = config.jinhuaSbLv
    info.jinhuaStar = config.jinhuaStar
    info.jinhuaZhangong = config.jinhuaZhangongMax

    local addAttr =  curConf[lv].addAttrCount[info.deng+1]
    if not addAttr then
        addAttr = curConf[lv].addAttrCount[#curConf[lv].addAttrCount]
    end
    info.upZhangong = addAttr.zhangong
    info.upMoney = addAttr.money

    for i = 1, #curConf[lv].addAttrCount do
        info.dengAttr[i].key = curConf[lv].addAttrCount[i].type
        info.dengAttr[i].value = curConf[lv].addAttrCount[i].value
    end
    info.dengAttr[0] = #curConf[lv].addAttrCount

    if info.isHave == 1 then
        makeMaterialGrid(human, info.item, id, config.upStarItem, config.upStar[info.star+1] or 1 , 2)
    else
        makeMaterialGrid(human, info.item, id, config.activeCond[1], config.activeCond[2], 1)
    end
    info.upStarMoney = config.upStarMoney[info.star+1] or 0
    --保存到战斗力到数据库
    if data then
        data.zhandouli = info.zhandouli
    end
    --发送到排行榜
    if 0 ~= human.db.putonShenbing then
        local sendMsg = Msg.lw.LW_CHECK_RANK_CHANGE
        sendMsg.type = RankDefine.SB_RANK_TYPE
        sendMsg.otherInfo = info.zhandouli
        Msg.send2world(sendMsg, human._id)
        YYDaBiao.checkCanGet(human, AcvityDefine.OPERATEACT_TYPE_SHENBING)
    end
end
function sendShenbingList(human)
    local msg = Msg.gc.GC_SHENBING_QUERY
    local len = 0
    msg.feedYinliang = 10000
    for i = 1, #sbMainConfig do
        len = len + 1
        setShenbingInfo(human, i, msg.info[len])
    end
    msg.info[0] = len

    local attr = getAllAttr(human)
    len = 0
    for k, v in pairs(attr) do
        len = len +1
        msg.attr[len].key = k
        msg.attr[len].value = v
        if len == 32 then
            break
        end

    end
    msg.attr[0] = len
    Msg.send(msg, human.fd)
end

--更新单个神兵信息
function updateShenbing(human, id)
    local msg = Msg.gc.GC_UPDATE_SHENBING
    setShenbingInfo(human, id, msg.info[1])
    msg.info[0] = 1

    local attr = getAllAttr(human)
    local len = 0
    for k, v in pairs(attr) do
        len = len +1
        msg.attr[len].key = k
        msg.attr[len].value = v
        if len == 32 then
            break
        end
    end
    msg.attr[0] = len
    Msg.send(msg, human.fd)
end

--装备神兵
function putOnSb(human, id)
    local config = sbMainConfig[id]
    if not config then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_EXIST)
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    if human.db.putonShenbing ~= 0 and human.db.putonShenbing ~= id and ObjHuman.checkIsInFighting(human) then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_FIGHT_NOT_CHANGE)
        return
    end
    if human.db.putonShenbing ~= 0 and human.db.putonShenbing ~= id and Cmds.passive.awake(human) then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_AWAKE_NOT_CHANGE)
        return
    end
    local old = human.db.putonShenbing
    human.db.putonShenbing = id
    human.sbType = nil
    if old ~= 0 then
        for i = 1, #config.haveSkill do
            if data.skillLv[i-1] > 0 then
                CoolDown.doCoolDown(human, config.haveSkill[i])
            end
        end
    end
    updateShenbing(human, id)
    if old ~= 0 then
        updateShenbing(human, old)

    end
    ObjHuman.doCalc(human)
    --更新技能
    SkillNotify.GC_SKILL_LIST(human)
    SkillNotify.GC_SKILL_LIST_CHANGE(human)
    SkillNotify.GC_SKILL_MAIN_MENU(human)

    Status.sendViewStatus(human, true)
end

function getShenbingType(human)
    if human.sbType then
        return human.sbType
    end
    local config = sbMainConfig[human.db.putonShenbing]
    if not config then
        human.sbType = 0
        return 0
    end
    human.sbType = config.type
    return config.type
end
--激活

function active(human, id)
    local config = sbMainConfig[id]
    if not config then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_EXIST)
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_HAD)
        return
    end

    local itemid = config.activeCond[1]
    local cnt = config.activeCond[2]

    if BagLogic.getItemCount(human, itemid) < cnt then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_CANT_ACTIVE, ItemDefine.getValue(itemid, "name")))
        return
    end

    BagLogic.delItemsById(human, itemid, cnt, "shenbing_active")


    ObjHuman.addShenbing(human, id, config.initStar)
    updateShenbing(human, id)
    Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_ACTIVE_OK)
    ObjHuman.doCalc(human)

    Log.write(Log.LOGID_OSS_SHENBING_ACTIVE, human._id, human.account, human.name, human.db.lv, id, itemid, cnt, human.db.shenbingLen)

end

-- 点灯
function levelUp(human, id, fromItem)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    local curConfig = sbConfig[config.sbName]
    if not curConfig then
        return
    end
    if data.deng >= 8 and (data.lv == MAX_STRENGTH_LV or data.lv >= human.db.lv) then
        return  --最高级
    end
    local dengConfig = curConfig[data.lv]

    if not fromItem then
        local zg = ObjHuman.getZhangong(human)
        if zg < dengConfig.addAttrCount[data.deng+1].zhangong then
            Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_ZHANGONG_NO)
            return
        end
        local yl = ObjHuman.getYinliang(human)
        if yl < dengConfig.addAttrCount[data.deng+1].money then
            Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_YINLIANG_NO)
            return
        end
        ObjHuman.decYinliang(human, dengConfig.addAttrCount[data.deng+1].money, "shenbing_deng")
        ObjHuman.decZhangong(human, dengConfig.addAttrCount[data.deng+1].zhangong, "shenbing_deng")
    end

    data.deng = data.deng + 1
    checkSkill(human, data, curConfig, dengConfig, false, config)
    if not fromItem then
        updateShenbing(human, id)
        ObjHuman.doCalc(human)
    end
    
    OfficialLogic.checkOneCondition(human, "sbLv")
    Log.write(Log.LOGID_OSS_SHENBING_STRENGTH, human._id, human.account, human.name, human.db.lv, id, data.lv, data.deng)

    TaskCallbacks.taskInteractCB(human, TaskDefine.TASK_INTERACT_STRENGTH_SB)
    return true
end

function checkStatus(human, id, isCombat)
    local config = sbMainConfig[id]
    if not config then
        if isCombat then
            Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.ITEM_ERR_SHENGBING_NOCOMBAT)
        end
        return false
    end

    local curConfig = sbConfig[config.sbName]
    if not curConfig then
        return false
    end

    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return false
    end

    if data.lv == MAX_STRENGTH_LV or data.lv >= human.db.lv then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.ITEM_ERR_SHENGBING_END)
        return false
    end
    return true
end

function onGetCombatShengBingLv(human)
    local data = ObjHuman.getShenbing(human, human.db.putonShenbing)
    if data then
        return data.lv
    end
    return nil
end

function onAddStar(human, id, star)
    local nSend = true
    local nLen = 0
    for i = 1, star do
        if not levelUp(human, id, true) then
            nSend = false
            break
        end
        nLen = nLen + 1
    end
    if nLen > 0 then
        updateShenbing(human, id)
        ObjHuman.doCalc(human)
    else
        return false
    end
    return true
end

function onAddLv(human, id, lv)
    local config = sbMainConfig[id]
    if not config then
        return false
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return false
    end
    local curConfig = sbConfig[config.sbName]
    if not curConfig then
        return false
    end
    if data.lv + lv <= #curConfig and data.lv + lv <= human.db.lv then --点满升级
        local dengConfig = curConfig[data.lv]
        local oldSkillcnt =  dengConfig.haveSkillCount
        data.lv = data.lv +lv
        dengConfig = curConfig[data.lv]
        if dengConfig.haveSkillCount > oldSkillcnt then
            --激活技能
            local index
            for i = oldSkillcnt +1, dengConfig.haveSkillCount do
                data.skillLv[i-1] = 1
                index = i
            end

            if human.db.putonShenbing == data.id then
                SkillNotify.GC_SKILL_LIST(human)
                SkillNotify.GC_SKILL_LIST_CHANGE(human)
                SkillNotify.GC_SKILL_MAIN_MENU(human)
                SkillNotify.GC_SKILL_NEW(human, index, config.haveSkill[index])
            end
        end
        updateShenbing(human, id)
        return true
    end
    return false
end

function checkSkill(human, data, curConfig, dengConfig, notify, config)
    local oldSkillcnt =  dengConfig.haveSkillCount
    if data.deng >= 8 and data.lv + 1 <= #curConfig and data.lv + 1 <= human.db.lv then --点满升级
        data.deng = 0
        data.lv = data.lv +1
        dengConfig = curConfig[data.lv]
        if dengConfig.haveSkillCount > oldSkillcnt then
            --激活技能
            local index
            for i = oldSkillcnt +1, dengConfig.haveSkillCount do
                data.skillLv[i-1] = 1
                index = i
            end

            if human.db.putonShenbing == data.id then
                SkillNotify.GC_SKILL_LIST(human)
                SkillNotify.GC_SKILL_LIST_CHANGE(human)
                SkillNotify.GC_SKILL_MAIN_MENU(human)
                SkillNotify.GC_SKILL_NEW(human, index, config.haveSkill[index])
            end
        end
        if notify then
            updateShenbing(human, data.id)
        end
    end
end


function onSkillUpGrade(human, sbId, skillId, skillLv)
    updateShenbing(human, sbId)

    if human.db.putonShenbing == sbId then
        SkillNotify.GC_SKILL_LIST(human)
        SkillNotify.GC_SKILL_LIST_CHANGE(human)
        SkillNotify.GC_SKILL_MAIN_MENU(human)
    end

    Log.write(Log.LOGID_OSS_SHENBING_SKILL_UP, human._id, human.account, human.name, human.db.lv, sbId, skillId, skillLv)
    TaskCallbacks.taskInteractCB(human, TaskDefine.TASK_INTERACT_UPSKILL_SB)

end
function upStar(human, id)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    if data.star == 5 then
        return
    end

    if BagLogic.getItemCount(human, config.upStarItem) < config.upStar[data.star+1] then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_STAR_NO_MATRAIL, ItemDefine.getValue(config.upStarItem, "name")))
        return
    end
    if ObjHuman.getYinliang(human) < config.upStarMoney[data.star+1] then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_STAR_NO_MONEY)
        return
    end

    ObjHuman.decYinliang(human, config.upStarMoney[data.star+1], "shenbing_star")

    BagLogic.delItemsById(human, config.upStarItem, config.upStar[data.star+1], "shenbing_star")
    data.star  = data.star + 1
    updateShenbing(human, id)
    Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_STAR_OK)
    ObjHuman.doCalc(human)
    if data.star == 1 then
        Status.sendViewStatus(human, true)
    end
    Log.write(Log.LOGID_OSS_SHENBING_STAR, human._id, human.account, human.name, human.db.lv, id, data.star)
    TaskCallbacks.taskInteractCB(human, TaskDefine.TASK_INTERACT_UPSTAR_SB)
    Broadcast.sendBroadcast2World(Lang.UP+Lang.GROSSIP, string.format(Lang.SHENBING_STAR_BROADCAST, HtmlUtil.fontName(human.name, human._id), config.sbMingzi, data.star, human._id))

end


function jinhua(human, id)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    if data.jinhua == 1 then -- 已经进化
        return
    end
    if data.lv < config.jinhuaSbLv then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_JINHUA_LV, config.jinhuaSbLv))
        return
    end
    if data.star < config.jinhuaStar then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_JINHUA_STAR, config.jinhuaStar))
        return
    end
    if human.db.zhangongHistory < config.jinhuaZhangongMax then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_JINHUA_ZG, config.jinhuaZhangongMax))
        return
    end
    data.jinhua = 1
    updateShenbing(human, id)
    Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_JINHUA_OK)
    SkillNotify.GC_SKILL_MAIN_MENU(human)
    Status.sendViewStatus(human, true)
end

local ATTR_CACHE = {}
function getAttr(id, lv, deng, star, human, data)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    for k in pairs(ATTR_CACHE) do
        ATTR_CACHE[k] = nil
    end
    local strengConf = sbConfig[config.sbName]
    local attr = strengConf[lv].attr
    for k, v in pairs(attr) do
        ATTR_CACHE[k] = v
    end
    attr = strengConf[lv].addAttrCount
    for i = 1, deng do
        ATTR_CACHE[attr[i].type]   = ATTR_CACHE[attr[i].type] or 0
        ATTR_CACHE[attr[i].type]   = ATTR_CACHE[attr[i].type] + attr[i].value
    end

    attr = config.starTotalAttr[star]
    if attr then
        for k, v in pairs(attr) do
            ATTR_CACHE[k] = ATTR_CACHE[k] or 0
            ATTR_CACHE[k] = ATTR_CACHE[k] + v
        end
    end

    if human and id == human.db.putonShenbing then --需要计算佩带属性
        attr = config.starTotalEquipAttr[star]
        if attr then
            for k, v in pairs(attr) do
                ATTR_CACHE[k] = ATTR_CACHE[k] or 0
                ATTR_CACHE[k] = ATTR_CACHE[k] + v
            end
        end
    end

    --加培养属性
    if data then
        local len = #config.feedAttr
        if len > 8 then len = 8 end
        for j = 1, len do
            local k = config.feedAttr[j][1]
            ATTR_CACHE[k] = ATTR_CACHE[k] or 0
            ATTR_CACHE[k] = ATTR_CACHE[k] + data.feedAttr[j-1]
            if ATTR_CACHE[k] == 0 then
                ATTR_CACHE[k] = nil
            end
        end
    end
    return ATTR_CACHE
end


function getAllAttr(human)
    for k in pairs(ATTR_CACHE) do
        ATTR_CACHE[k] = nil
    end
    for i = 0, human.db.shenbingLen - 1  do
        local data = human.db.shenbing[i]
        local config = sbMainConfig[data.id]
        if config then
            local strengConf = sbConfig[config.sbName]
            local attr = strengConf[data.lv].attr
            for k, v in pairs(attr) do
                ATTR_CACHE[k] = ATTR_CACHE[k] or 0
                ATTR_CACHE[k] = ATTR_CACHE[k] + v
            end
            attr = strengConf[data.lv].addAttrCount
            for j = 1, data.deng do
                ATTR_CACHE[attr[j].type]   = ATTR_CACHE[attr[j].type] or 0
                ATTR_CACHE[attr[j].type]   = ATTR_CACHE[attr[j].type] + attr[j].value
            end

            attr = config.starTotalAttr[data.star]
            if attr then
                for k, v in pairs(attr) do
                    ATTR_CACHE[k] = ATTR_CACHE[k] or 0
                    ATTR_CACHE[k] = ATTR_CACHE[k] + v
                end
            end
            if data.id == human.db.putonShenbing then --加佩带属性
                attr = config.starTotalEquipAttr[data.star]
                if attr then
                    for k, v in pairs(attr) do
                        ATTR_CACHE[k] = ATTR_CACHE[k] or 0
                        ATTR_CACHE[k] = ATTR_CACHE[k] + v
                    end
                end
            end
            --加培养属性
            local len = #config.feedAttr
            if len > 8 then len = 8 end
            for j = 1, len do
                local k = config.feedAttr[j][1]
                ATTR_CACHE[k] = ATTR_CACHE[k] or 0
                ATTR_CACHE[k] = ATTR_CACHE[k] + data.feedAttr[j-1]
                if ATTR_CACHE[k] == 0 then
                    ATTR_CACHE[k] = nil
                end
            end
        end
    end
    return ATTR_CACHE
end

function doCalc(human)
    local attr = getAllAttr(human)
    for k, v in pairs(attr) do
        human.attr[k]  = human.attr[k] + v
    end
end


function onLevelUp(human)
    for i = 0, human.db.shenbingLen - 1  do
        local data = human.db.shenbing[i]
        local config = sbMainConfig[data.id]
        local curConfig = sbConfig[config.sbName]
        local dengConfig =   curConfig[data.lv]
        checkSkill(human, data, curConfig, dengConfig, true, config)
    end
end

function getPutonSbName(human)
    if human.db.putonShenbing == 0 then return "" end
    return sbConfig.shenbing[human.db.putonShenbing].sbMingzi
end
function getPutonSbIcon(human)
    if human.db.putonShenbing == 0 then return nil end
    return sbConfig.shenbing[human.db.putonShenbing].icon[1]
end


function chooseShenbing(human, id)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    if human.db.shenbingLen > 0 then
        return
    end
    Buffer.removeID(82, human)
    ObjHuman.addShenbing(human, id, config.initStar)
    human.db.putonShenbing = id
    --  updateShenbing(human, id)
    ObjHuman.doCalc(human)

    --更新技能
    SkillNotify.GC_SKILL_LIST(human)
    SkillNotify.GC_SKILL_LIST_CHANGE(human)
    SkillNotify.GC_SKILL_MAIN_MENU(human)
    Status.sendViewStatus(human, true)

    TaskCallbacks.taskInteractCB(human, TaskDefine.TASK_INTERACT_CHOOSE_SB)



    Log.write(Log.LOGID_OSS_SHENBING_CHOOSE, human._id, human.account, human.name, human.db.lv, id)
    Log.write(Log.LOGID_OSS_SHENBING_ACTIVE, human._id, human.account, human.name, human.db.lv, id, 0, 0, 1)

end

-- 是否培养已满
function isFeedFull(human, id, config, data)
    local len = #config.feedAttr
    if len > 8 then
        len = 8
    end
    for i = 1, len do
        if data.feedAttr[i-1] < config.feedAttr[i][2] then
            return
        end
    end
    return true
end
--计算培养值
function randFeed(human,  id, config, data, len)
    if isFeedFull(human, id, config, data) then
        return
    end

    local process = 0
    for i = 1, len do
        process = process + data.feedAttr[i-1]/config.feedAttr[i][2]
    end
    process = math.floor(process / len * 100)

    local feed
    for i = 1, #feedConfig do
        if process < feedConfig[i].progress then
            feed = feedConfig[i]
            break
        end
    end
    if not feed then
        return
    end

    local attrCnt
    local sum = 0
    for i = 1, len do
        sum = sum + (feed.weight[i] or 0)
    end
    local randVal = math.random(1, sum)
    sum = 0
    for i = 1, len do
        sum = sum + (feed.weight[i] or 0)
        if sum >= randVal then
            attrCnt = i
            break
        end
    end
    local ret = {}
    local start = math.random(1,  len)
    local realCnt = 0
    for i = 1, len do
        if ret[config.feedAttr[start][1]] == nil and data.feedAttr[start-1] < config.feedAttr[start][2] and (attrCnt >= len or math.random(1, 10000)%2  == 1) then
            ret[config.feedAttr[start][1]] = math.random(config.feedAttr[start][3], config.feedAttr[start][4])
            realCnt = realCnt + 1
        end
        start = start + 1
        if start > len then
            start = 1
        end
        if realCnt == attrCnt then
            break
        end
    end
    if realCnt < attrCnt then --再算一篇，无随机属性的
        for i = 1, len do
            if ret[config.feedAttr[start][1]] == nil and data.feedAttr[start-1] < config.feedAttr[start][2] then
                ret[config.feedAttr[start][1]] = math.random(config.feedAttr[start][3], config.feedAttr[start][4])
                realCnt = realCnt + 1
            end
            start = start + 1
            if start > len then
                start = 1
            end
            if realCnt == attrCnt then
                break
            end
        end
    end

    if realCnt > 0 then
        return ret
    end
end

--培养数据查询
function feedQuery(human, id, add)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    local msg = Msg.gc.GC_SHENBING_FEED_QUERY
    msg.id = id
    local len = #config.feedAttr
    if len > 8 then
        len = 8
    end
    for i = len + 1, 8 do
        data.feedAttr[i-1] = 0
    end
    local full =  isFeedFull(human, id, config, data)
    for i = 1, len do
        msg.feedAttr[i].key = config.feedAttr[i][1]
        msg.feedAttr[i].value = add and add[config.feedAttr[i][1]] and data.feedAttr[i-1]-add[config.feedAttr[i][1]] or data.feedAttr[i-1]
        if full or data.feedAttr[i-1] >= config.feedAttr[i][2] then
            msg.feedAddVal[i] = -1
        else
            msg.feedAddVal[i] = add and add[config.feedAttr[i][1]] or 0
        end
    end
    msg.feedAttr[0] = len
    msg.feedAddVal[0] = len
    Msg.send(msg, human.fd)
end

--神兵培养
function feed(human, id)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    if data.star ~= 5 then
        return
    end
    if ObjHuman.getYinliang(human) < 10000 then
      return Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.YINLIANG_NOT_ENOUGH)
    end
    if BagLogic.getItemCount(human, config.upStarItem) < 1 then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_FEED_NO_MATRAIL, ItemDefine.getValue(config.upStarItem, "name")))
        return
    end
    local len = #config.feedAttr
    if len > 8 then
        len = 8
    end
    local add = randFeed(human, id, config, data, len)
    if not add then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_FEED_FULL)
        return
    end
    ObjHuman.decYinliang(human, 10000,"shenbing_feed")
    BagLogic.delItemsById(human, config.upStarItem, 1, "shenbing_feed")
    for i = 1, len do
        if add[config.feedAttr[i][1]] then
            data.feedAttr[i-1] = data.feedAttr[i-1] + add[config.feedAttr[i][1]]
            if data.feedAttr[i-1] > config.feedAttr[i][2] then
                data.feedAttr[i-1] = config.feedAttr[i][2]
            end
        end
    end
    Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_FEED_OK)
    feedQuery(human, id, add)
    updateShenbing(human, id)
    ObjHuman.doCalc(human)
end

function feedMulti(human, id, cnt)
    if cnt > 99 then
        cnt = 99
    end
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    if data.star ~= 5 then
        return
    end
    if ObjHuman.getYinliang(human) < 10000 * cnt then
      return Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.YINLIANG_NOT_ENOUGH)
    end
    local hadCnt = BagLogic.getItemCount(human, config.upStarItem)
    if hadCnt < 1 then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_FEED_NO_MATRAIL, ItemDefine.getValue(config.upStarItem, "name")))
        return
    end
    if cnt > hadCnt then
        cnt = hadCnt
    end
    local len = #config.feedAttr
    if len > 8 then
        len = 8
    end
    local add = randFeed(human, id, config, data, len)
    if not add then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_FEED_FULL)
        return
    end
    
    local del = 0
    local totalAdd = {}
    for k = 1, cnt do
         if not add then
            break
         end      
         for i = 1, len do
           if add[config.feedAttr[i][1]] then
              data.feedAttr[i-1] = data.feedAttr[i-1] + add[config.feedAttr[i][1]]
              if data.feedAttr[i-1] > config.feedAttr[i][2] then
                data.feedAttr[i-1] = config.feedAttr[i][2]
              end
           end
         end        
         del =  del + 1 
         for kk,vv in pairs(add) do
            if totalAdd[kk] then
                totalAdd[kk] = totalAdd[kk] + vv
            else
                totalAdd[kk] = vv
            end
         end
         add = randFeed(human, id, config, data, len)
    end
    ObjHuman.decYinliang(human, 10000 * del,"shenbing_feed")
    BagLogic.delItemsById(human, config.upStarItem, del, "shenbing_feed")
    Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_FEED_OK)
    feedQuery(human, id, totalAdd)
    updateShenbing(human, id)
    ObjHuman.doCalc(human)
    
    local mm = Msg.gc.GC_SHENBING_MULTI_FEED
    mm.id = id
    mm.cnt = del
    Msg.send(mm, human.fd)
end

function juejiQuery(human)
    local msg = Msg.gc.GC_SHENBING_JUEJI_QUERY
    if msg.list[0] == nil then
        local len = 0
        local node
        for id, config in pairs(sbMainConfig) do
            len = len + 1
            node = msg.list[len]
            node.id = id
            node.yinliang = config.juejiYinliang
            makeMaterialGrid(human, node.item, id, config.juejiItem, config.juejiItemCount , 3)
        end
        msg.list[0] = len
    end
    Msg.send(msg, human.fd)
end

function juejiActive(human, id)
    local config = sbMainConfig[id]
    if not config then
        return
    end
    local data = ObjHuman.getShenbing(human, id)
    if not data then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_NOT_HAVE)
        return
    end
    if data.jueji ~= 0 then
        return
    end

    if BagLogic.getItemCount(human, config.juejiItem) < config.juejiItemCount then
        Broadcast.sendBroadcast(human, Lang.MOUSE, string.format(Lang.SHENBING_JUEJI_NO_MATRAIL, ItemDefine.getValue(config.juejiItem, "name")))
        return
    end

    if ObjHuman.getYinliang(human) < config.juejiYinliang then
        Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_JUEJI_NO_MONEY)
        return
    end

    ObjHuman.decYinliang(human, config.juejiYinliang, "shenbing_jueji")

    BagLogic.delItemsById(human, config.juejiItem, config.juejiItemCount, "shenbing_jueji")

    data.jueji = 1
    updateShenbing(human, id)

    Broadcast.sendBroadcast(human, Lang.MOUSE, Lang.SHENBING_JUEJI_OK)
end


function notifyChooseShenbing(human)
    local msg = Msg.gc.GC_SHENBING_CHOOSE
    if msg.ids[0]~=3 then
        msg.ids[1] = 1
        msg.ids[2] = 2
        msg.ids[3] = 3
        msg.ids[0] = 3
    end
    Msg.send(msg, human.fd)
end

--额外技能等级战斗力
function getSkillZhandouli(human, id)
    local data = ObjHuman.getShenbing(human, id)
    if data == nil then
        return 0
    end
    local config = sbMainConfig[id]
    local value = 0
    local len = #config.haveSkill
    if len > 4 then
        len =4
    end
    for i = 1, len do
        value = value + data.skillLv[i-1]* ZHANDOULI_CALC[i]
    end
    return value
end

function getSkillList(human)
    local data = ObjHuman.getShenbing(human, human.db.putonShenbing)
    if data == nil then
        return
    end
    local config = sbMainConfig[human.db.putonShenbing]
    if not config then
        return
    end
    local len = #config.haveSkill
    if len > 4 then
        len = 4
    end
    local list = {}
    for i = len, 1, -1 do
        if data.skillLv[i-1] > 0 then
            list[#list+1] = config.haveSkill[i]
        end
    end
    return list
end

function setSbShowInfo(info, id)
    for i=1, #sbMainConfig do
        if i == id then
            info.id = 0
            info.type = 3
            info.effect = sbMainConfig[i].icon[1] or 0
            local data = getAttr(id, 0, 0, 0)
            local len = 0
            for k, v in pairs(data) do
                len = len + 1
                info.attr[len].key = k
                info.attr[len].value = v
            end
            info.attr[0] = len
            info.power = RoleAttr.calHumanPower(data)
        end
    end
end

function getShenbingLvCount(human, lv)
  local count = 0
  for i=1, #sbMainConfig do
    local data = ObjHuman.getShenbing(human, i)
    if data and data.lv > lv then
      count = count + 1
    end
  end
  return count
end
